/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lbim.protocol;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

import lbim.client.model.Account;
import lbim.client.model.LocXy;
import lbim.client.model.Request;
import lbim.client.model.Response;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;

/**
 *
 * @author Jestan
 */
public class LbImProtocol implements ResponseListener {

    public  String sessionId = "null";
    private Account account;

    private CirChannelHandler channelHandler;


    public LbImProtocol(Account account) {
        this.account = account;
    }

    public void sendLoginMessage() {
        StringBuffer sb = new StringBuffer();
        sb.append("<LbImMessage>")
                .append("<UserName>")
                .append(account.getUserName())
                .append("</UserName>")
                .append("<Password>")
                .append(account.getPassword())
                .append("</Password>")
                .append("</LbImMessage>");

        sendMessage(sb.toString(), Request.LOG_IN);

    }

    public void sendPresenceReqMessage() {
        StringBuffer sb = new StringBuffer();
        sb.append("<LbImMessage>")
          .append("</LbImMessage>");

        sendMessage(sb.toString(), Request.PRESENCE_REQ_MESSAGE);
    }

    public void sendLogoutMessage() {
        channelHandler.shutdown();
        StringBuffer sb = new StringBuffer();
        sb.append("<LbImMessage>")
          .append("</LbImMessage>");

        sendMessage(sb.toString(), Request.LOG_OUT);

    }

    public void sendPoolingMessage() {
        StringBuffer sb = new StringBuffer();
        sb.append("<LbImMessage>")
          .append("</LbImMessage>");
        sendMessage(sb.toString(), Request.POOLING_MESSAGE);

    }

    public void sendChatMessage(String message, String receiver) {
        StringBuffer sb = new StringBuffer();
        sb.append("<LbImMessage>")
          .append("<Sender>")
          .append(account.getUserName())
          .append("</Sender>")
          .append("<Receiver>")
          .append(receiver)
          .append("</Receiver>")
          .append("<Content>")
          .append(message)
          .append("</Content>")
          .append("</LbImMessage>");
        sendMessage(sb.toString(), Request.CHAT_MESSAGE);

    }

    public void sendLocationUpdate(LocXy xy, String res, int zoom) {
        StringBuffer sb = new StringBuffer();
        sb.append("<LbImMessage>")
          .append("<CellId>")
          .append("Unknown")
          .append("</CellId>")
          .append("<Logitude>")
          .append(xy.getLong())
          .append("</Logitude>")
          .append("<Latitude>")
          .append(xy.getLat())
          .append("</Latitude>")
          .append("<Size>")
          .append(res)
          .append("</Size>")
          .append("<Zoom>")
          .append(zoom)
          .append("</Zoom>")
          .append("</LbImMessage>");
        sendMessage(sb.toString(), Request.LOCATION_UPDATE);
    }

    public void sendLocationUpdate(String cellId) {
        StringBuffer sb = new StringBuffer();
        sb.append("<LbImMessage>")
          .append("<CellId>")
          .append(cellId)
          .append("</CellId>")
          .append("<Logitude>")
          .append("Unknown")
          .append("</Logitude>")
          .append("<Latitude>")
          .append("Unknown")
          .append("</Latitude>")
          .append("</LbImMessage>");
        sendMessage(sb.toString(), Request.LOCATION_UPDATE);
    }

    private void sendMessage(String xmlMessage, int type) {
        SenderThread thread = new SenderThread(this, account.getServrURL(), xmlMessage, type, sessionId);
        thread.start();
    }

    public void responseReceived(DataInputStream in, String responseType, String responseCode, String contentLength) {
        int type = Integer.parseInt(responseType);
        int status = Integer.parseInt(responseCode);
        switch (type) {
            case Response.LOG_IN:
                if (status == Response.OK) {
                    System.out.println("[LbImProtocol] Login success, status code :" + status);
                    handleLoginResponse(in);
                } else {
                    System.out.println("[LbImProtocol] Login failed, status code :" + status);
                }
                break;
            case Response.CHAT_MESSAGE:
                if(status == Response.OK) {
                    System.out.println("[LbImProtocol] New message received :" + status);
                    handleChatMessage(in);
                } else {
                    System.out.println("[LbImProtocol] Error occured while receiving the msg :" + status);
                }
                break;
            case Response.LOCATION_UPDATE:
                if (status == Response.OK) {
                    System.out.println("[LbImProtocol] Location update received, status code :" + status+" byte[] length:"+ contentLength);
                    int len = Integer.parseInt(contentLength);
                    handleLocationUpdate(in, len);
                } else {
                    System.out.println("[LbImProtocol] Location update received :" + status);
                }
                break;
            case Response.LOG_OUT:
                System.out.println("[LbImProtocol] Logout Response received");
                handleLogoutResponse(in, status);
                break;
            case Response.PRESENCE_RESPONSE_MESSAGE:
                System.out.println("[LbImProtocol] Presence Response received");
                handlePresenceResponse(in);
                break;

        }

    }

    private void handleLoginResponse(DataInputStream in) {
        try {
            InputStreamReader reader = new InputStreamReader(in);
            KXmlParser parser = new KXmlParser();
            parser.setInput(reader);
            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, "LbImMessage");
            while (parser.next() != XmlPullParser.END_DOCUMENT) {
                if (parser.getEventType() == XmlPullParser.START_TAG) {
                    if (parser.getName().equals("SessionId")) {
                        String sid = parser.nextText();
                        this.sessionId = sid;
                        System.out.println("[LbImProtocol] session id :"+sid);
                    } else if (parser.getName().equals("Discription")) {
                        String description = parser.nextText();
                        System.out.println("[LbImProtocol] description :"+description);
                    } 
                }
            }

            channelHandler = new CirChannelHandler(this, account.getUserName(), sessionId);
            account.getLoginListener().loginResponseReceived(Response.OK);
        } catch (Throwable e) {
            System.out.println(e);
        }
    }

    private void handleLogoutResponse(DataInputStream in, int status) {
        try {
            String description = "";
            InputStreamReader reader = new InputStreamReader(in);
            KXmlParser parser = new KXmlParser();
            parser.setInput(reader);
            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, "LbImMessage");
            while (parser.next() != XmlPullParser.END_DOCUMENT) {
                if (parser.getEventType() == XmlPullParser.START_TAG) {
                    if (parser.getName().equals("Discription")) {
                        description = parser.nextText();
                        System.out.println("[LbImProtocol] description :" + description);
                    }
                }
            }

            account.getLogoutListener().logoutResponseReceived(status, description);

        } catch (Throwable e) {
            System.out.println(e);
        }
    }

    private void handleChatMessage(DataInputStream in) {
         try {
             String sender = "";
             String content = "";
            InputStreamReader reader = new InputStreamReader(in);
            KXmlParser parser = new KXmlParser();
            parser.setInput(reader);
            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, "LbImMessage");
            while (parser.next() != XmlPullParser.END_DOCUMENT) {
                if (parser.getEventType() == XmlPullParser.START_TAG) {
                    if (parser.getName().equals("Sender")) {
                        sender = parser.nextText();
                        System.out.println("[LbImProtocol] Sender :" + sender);
                    }else if (parser.getName().equals("Content")) {
                        content = parser.nextText();
                        System.out.println("[LbImProtocol] Content :"+ content);
                    }
                }
            }
            account.getChatListener().messageReceived(sender, content);
        } catch (Throwable e) {
            System.out.println(e);
        }
    }

    private void handleLocationUpdate(DataInputStream in, int len) {
        byte[] data = new byte[len];
        try {
            in.readFully(data);
            account.getMapUpdateListener().mapDataRecieved(data);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private void handlePresenceResponse(DataInputStream in) {
        try {
            String presenceList = "";
            InputStreamReader reader = new InputStreamReader(in);
            KXmlParser parser = new KXmlParser();
            parser.setInput(reader);
            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, "LbImMessage");
            while (parser.next() != XmlPullParser.END_DOCUMENT) {
                if (parser.getEventType() == XmlPullParser.START_TAG) {
                    if (parser.getName().equals("PresenceList")) {
                        presenceList = parser.nextText();
                        System.out.println("[LbImProtocol] PresenceList :" + presenceList);
                    }
                }
            }
            account.getPresenceListener().presenceResponseReceived(presenceList);
        } catch (Throwable e) {
            System.out.println(e);
        }
    }

}
